package com.bwie.es.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.bwie.common.constants.TokenConstants;
import com.bwie.common.domain.Admin;
import com.bwie.common.domain.Shop;
import com.bwie.common.domain.Statistics;
import com.bwie.common.domain.request.ShopRequest;
import com.bwie.common.result.PageResult;
import com.bwie.common.result.Result;
import com.bwie.common.utils.JwtUtils;
import com.bwie.common.utils.StringUtils;
import com.bwie.es.service.EsService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class EsServiceImpl implements EsService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    private static final String INDEX_NAME = "shop";

    /**
     * ES查询店铺列表
     * @param request
     * @return
     */
    @Override
    public Result<PageResult<Shop>> esInquire(ShopRequest request) {
        long total = 0;
        List<Shop> shopArrayList = new ArrayList<>();
        try {
            SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            if (!StringUtils.isBlank(request.getShopName())){
                boolQuery.must(QueryBuilders.matchQuery("shopName",request.getShopName()));
            }
            if (request.getStartTime() != null){
                boolQuery.must(QueryBuilders.rangeQuery("shopEntryTime").gte(request.getStartTime().getTime()));
            }
            if (request.getEndTime() != null){
                boolQuery.must(QueryBuilders.rangeQuery("shopEntryTime").lte(request.getEndTime().getTime()));
            }
            Admin admin = info();
            Integer adminId = admin.getAdminId();
            if (adminId == 2){
                boolQuery.must(QueryBuilders.termQuery("shopAdminId",adminId));
            }
            searchSourceBuilder.query(boolQuery);
            searchSourceBuilder.from((request.getPageNum() - 1) * request.getPageSize());
            searchSourceBuilder.size(request.getPageSize());
            searchSourceBuilder.highlighter(
                    new HighlightBuilder()
                            .field("shopName")
                            .preTags("<span style=\"color:red;\">")
                            .postTags("</span>")
            );
        searchRequest.source(searchSourceBuilder);
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits hits = searchResponse.getHits();
            total = hits.getTotalHits().value;

            SearchHit[] searchHits = hits.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Shop shop = JSONObject.parseObject(sourceAsString, Shop.class);
                shop.setShopId(Integer.valueOf(searchHit.getId()));

                Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                if (highlightFields != null){
                    HighlightField highlightField = highlightFields.get("shopName");
                    if (highlightField != null){
                        Text[] fragments = highlightField.getFragments();
                        String str = "";
                        for (Text fragment : fragments) {
                            str += fragment;
                        }
                        shop.setShopName(str);
                    }
                }
                shopArrayList.add(shop);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return PageResult.toResult(total,shopArrayList);
    }

    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private Admin info(){
        String token = httpServletRequest.getHeader(TokenConstants.TOKEN);
        String userKey = JwtUtils.getUserKey(token);
        String admin = redisTemplate.opsForValue().get(TokenConstants.LOGIN_TOKEN_KEY + userKey);
        Admin admin1 = JSONObject.parseObject(admin, Admin.class);
        return admin1;
    }

    /**
     * 统计店铺状态
     * @return
     */
   @Override
   public List<Statistics> queryCount() {
       List<Statistics> statisticsArrayList = new ArrayList<>();
       try {
           SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
           SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
           TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("shop_number").field("shopFlag");
           searchSourceBuilder.aggregation(aggregationBuilder);
           searchRequest.source(searchSourceBuilder);
           SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
           Aggregations aggregations = searchResponse.getAggregations();
           Terms warrantyNumber = aggregations.get("shop_number");
           List<? extends Terms.Bucket> buckets = warrantyNumber.getBuckets();
           //遍历
           buckets.forEach(bucket -> {
               String keyAsString = bucket.getKeyAsString();
               long docCount = bucket.getDocCount();
               Statistics statistics = new Statistics();
               statistics.setStatisticsId(keyAsString);
               statistics.setStatisticsCount(docCount);
               statisticsArrayList.add(statistics);
           });
       } catch (Exception e) {
           throw new RuntimeException(e);
       }
       return statisticsArrayList;
   }
}
